//
//  NSString+Mango.m
//  Mango
//
//  Created by 胡超 on 2017/12/25.
//  Copyright © 2017年 胡超., ltd. All rights reserved.
//

#import <CommonCrypto/CommonCryptor.h>
#import <CommonCrypto/CommonDigest.h>

#import "NSString+Mango.h"
#import "NSData+Mango.h"

@implementation NSString (Mango)

- (NSString *)md5Str {
    return [self dataUsingEncoding:NSUTF8StringEncoding].md5Str;
}

- (NSString *)fileMd5Str {
    NSFileHandle *handle = [NSFileHandle fileHandleForReadingAtPath:self];
    if (handle == nil) {
        return nil;
    }
    CC_MD5_CTX md5;
    CC_MD5_Init(&md5);
    BOOL done = NO;
    while (!done) {
        NSData* fileData = [handle readDataOfLength:256];
        CC_MD5_Update(&md5, [fileData bytes], (CC_LONG)fileData.length);
        if ( [fileData length] == 0 ) done = YES;
    }
    unsigned char result[CC_MD5_DIGEST_LENGTH];
    CC_MD5_Final(result, &md5);
    NSMutableString *md5str = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH];
    for (int i=0; i<CC_MD5_DIGEST_LENGTH; i++) {
        [md5str appendFormat:@"%02x",result[i]];
    }
    return md5str.lowercaseString;
}

- (NSURL *)url {
    NSString *URLString = self.URLEncodedString;
    if (URLString) {
        if ([URLString hasPrefix:@"/"]) {
            return [NSURL fileURLWithPath:URLString];
        } else {
            return [NSURL URLWithString:URLString];
        }
    } else {
        return nil;
    }
}

- (NSString *)URLEncodedString {
    NSString *charactersToEscape = @"!*'();@+$,%[]";
    NSCharacterSet *allowedCharacters = [NSCharacterSet characterSetWithCharactersInString:charactersToEscape].invertedSet;
    return [self stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacters];
}

- (NSString *)URLDecodedString {
    return [self stringByRemovingPercentEncoding];
}

//- (NSString *(^)(NSDictionary *))addURLParameters {
//    return ^(NSDictionary *parameters) {
//        if (!parameters || ![parameters isKindOfClass:NSDictionary.class])
//            return self;
//        
//        NSURL *URL = [NSURL URLWithString:self.URLEncodedStr];
//        NSString *URLString = self;
//        if (URL.query)
//            URLString = [NSString stringWithFormat:@"%@&%@",URLString,parameters.urlQuery];
//        else
//            URLString = [NSString stringWithFormat:@"%@?%@",URLString,parameters.urlQuery];
//        
//        return URLString;
//    };
//}

#pragma mark - Formatter Date

- (NSDate *(^)(NSString *))formatToDate {
    return ^(NSString *dateFormat) {
        NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
        formatter.dateFormat = dateFormat;
        return [formatter dateFromString:self];
    };
}

#pragma mark - PinYin

- (NSString *)pinyinStr {
    if (self.length > 0) {
        NSMutableString *pinyin = [self mutableCopy];
        CFStringTransform((__bridge CFMutableStringRef)pinyin, NULL, kCFStringTransformMandarinLatin, NO);
        CFStringTransform((__bridge CFMutableStringRef)pinyin, NULL, kCFStringTransformStripDiacritics, NO);
        return [pinyin stringByReplacingOccurrencesOfString:@" " withString:@""];
    }
    return self;
}

- (NSString *)pinyinFirstWord {
    if (self.length > 0) {
        NSMutableString *pinyin = [[self substringToIndex:1] mutableCopy];
        CFStringTransform((__bridge CFMutableStringRef)pinyin, NULL, kCFStringTransformMandarinLatin, NO);
        CFStringTransform((__bridge CFMutableStringRef)pinyin, NULL, kCFStringTransformStripDiacritics, NO);
        return [pinyin substringToIndex:1].uppercaseString;
    }
    return self;
}

#pragma mark -

- (BOOL)isChinese {
    NSString *regex = @"(^[\u4e00-\u9fff]+$)";
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",regex];
    return [predicate evaluateWithObject:self];
}

- (BOOL)isContainsChinese {
    for (int i=0; i<self.length; i++) {
        int character = [self characterAtIndex:i];
        if (character >= 0x4e00 && character <= 0x9fff){
            return YES;
        }
    }
    return NO;
}

- (BOOL)isRealName {
    for (int i=0; i<self.length; i++) {
        int character = [self characterAtIndex:i];
        if (character == 0xb7) { // 姓名中点字符"·"
            continue;
        }
        if (character < 0x4e00 || character > 0x9fff) {
            return NO;
        }
    }
    return (YES && self.length);
}

- (BOOL)isValidIdentityNumber {
    // 判断是否是18位
    if (self.length != 18) {
        return NO;
    }
    // 判断是否17位数字开头，并以数字或者大写X或小写x结尾
    NSString *regex = @"^(\\d{14}|\\d{17})(\\d|[xX])$";
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",regex];
    if (![predicate evaluateWithObject:self]) {
        return NO;
    }

    //判断生日是否合法
    NSRange range = NSMakeRange(6,8);
    NSString *dateStr = [self substringWithRange:range];
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    formatter.dateFormat = @"yyyyMMdd";
    if (![formatter dateFromString:dateStr]) {
        return NO;
    }
    
    // 校验最后一位是否合法
    // 系数
    int nums[17] = {7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2};
    int sum = 0;
    for (int i=0; i<17; i++) {
        int j = [[self substringWithRange:NSMakeRange(i, 1)] intValue];
        sum += j*nums[i];
    }
    int idx = sum%11;// 计算校验码的索引
    NSString *last1 = @[@"1",@"0",@"x",@"9",@"8",@"7",@"6",@"5",@"4",@"3",@"2"][idx];
    NSString *last2 = [self substringWithRange:NSMakeRange(17, 1)].lowercaseString;
    
    return [last1 isEqualToString:last2];
}

#pragma mark - DES

- (NSString *)desEncryptString:(MGDESOptions)options key:(const void *)key iv:(const void *)iv {
    NSData *data = [self dataUsingEncoding:NSUTF8StringEncoding];
    NSData *encryptData = [data desEncryptData:options key:key iv:iv];
    return [encryptData base64EncodedStringWithOptions:0];
}

- (NSString *)desDecryptString:(MGDESOptions)options key:(const void *)key iv:(const void *)iv {
    NSData *data = [[NSData alloc] initWithBase64EncodedString:self options:0];
    NSData *decryptData = [data desDecryptData:options key:key iv:iv];
    return [[NSString alloc] initWithData:decryptData encoding:NSUTF8StringEncoding];
}

@end
